import { Callout, Tabs } from 'nextra/components';
import { Widget } from '@/components/demo/widget.tsx';
import LinkBadge from '@/components/ui/link-badge/link-badge.tsx';
import LinkBadgeGroup from '@/components/ui/link-badge/link-badge-group.tsx';

# Calendar

A calendar component for selecting and editing dates.

The calendar supports swipe gestures on mobile platforms, allowing users to navigate between pages by swiping left or right.

A [`FCalendarController`](https://pub.dev/documentation/forui/latest/forui.widgets.calendar/FCalendarController-class.html)
controls the date selection behavior, including single date, multiple dates, and date range selection.

<LinkBadgeGroup>
    <LinkBadge label="API Reference" href="https://pub.dev/documentation/forui/latest/forui.widgets.calendar/"/>
</LinkBadgeGroup>

<Callout type="info">
    `FCalendar` and all `FCalendarController`s return `DateTime`s in UTC timezone, truncated to the nearest day.
</Callout>

<Callout type="info">
  Hold `Shift` while scrolling to navigate through dates on desktop and web.
</Callout>

<Tabs items={['Preview', 'Code']}>
    <Tabs.Tab>
        <Widget name='calendar' query={{}} height={500}/>
    </Tabs.Tab>
    <Tabs.Tab>
        ```dart copy
        FCalendar(
          controller: FCalendarController.date(initialSelection: selected),
          start: DateTime(2000),
          end: DateTime(2030),
        );
        ```
    </Tabs.Tab>
</Tabs>

## CLI

To generate and customize this style:

```shell copy
dart run forui style create calendar
```

## Usage

### `FCalendar(...)`

```dart copy
FCalendar(
  controller: FCalendarController.date(
    initialSelection: DateTime(2024, 9, 13),
    selectable: (date) => allowedDates.contains(date),
  ),
  style: FCalendarStyle(...),
  dayBuilder: (context, data, child) => child!,
  start: DateTime(2024),
  end: DateTime(2030),
  today: DateTime(2024, 7, 14),
  initialType: FCalendarPickerType.yearMonth,
  initialMonth: DateTime(2024, 9),
  onMonthChange: (date) => print(date),
  onPress: (date) => print(date),
  onLongPress: (date) => print(date),
);
```

## Examples

### Single Date

<Tabs items={['Preview', 'Code']}>
    <Tabs.Tab>
        <Widget name='calendar' query={{}} height={500}/>
    </Tabs.Tab>
    <Tabs.Tab>
        ```dart {2} copy
        FCalendar(
          controller: FCalendarController.date(),
          start: DateTime(2000),
          end: DateTime(2030),
        );
        ```
    </Tabs.Tab>
</Tabs>

### Multiple Dates with Initial Selections

<Tabs items={['Preview', 'Code']}>
    <Tabs.Tab>
        <Widget name='calendar' variant='dates' query={{}} height={500}/>
    </Tabs.Tab>
    <Tabs.Tab>
        ```dart {2-4} copy
        FCalendar(
          controller: FCalendarController.dates(
            initialSelections: {DateTime(2024, 7, 17), DateTime(2024, 7, 20)},
          ),
          start: DateTime(2000),
          today: DateTime(2024, 7, 15),
          end: DateTime(2030),
        );
        ```
    </Tabs.Tab>
</Tabs>

### Unselectable Dates

<Tabs items={['Preview', 'Code']}>
    <Tabs.Tab>
        <Widget name='calendar' variant='unselectable' query={{}} height={500}/>
    </Tabs.Tab>
    <Tabs.Tab>
      ```dart {4} copy
      FCalendar(
        controller: FCalendarController.dates(
          initialSelections: {DateTime(2024, 7, 17), DateTime(2024, 7, 20)},
          selectable: (date) => !{DateTime(2024, 7, 18), DateTime(2024, 7, 19)}.contains(date),
        ),
        start: DateTime(2000),
        today: DateTime(2024, 7, 15),
        end: DateTime(2030),
      );
      ```
    </Tabs.Tab>
</Tabs>

### Range Selection with Initial Range

<Tabs items={['Preview', 'Code']}>
    <Tabs.Tab>
        <Widget name='calendar' variant='range' query={{}} height={500}/>
    </Tabs.Tab>
    <Tabs.Tab>
        ```dart {2-4} copy
        FCalendar(
          controller: FCalendarController.range(
            initialSelection: (DateTime(2024, 7, 17), DateTime(2024, 7, 20)),
          ),
          start: DateTime(2000),
          today: DateTime(2024, 7, 15),
          end: DateTime(2030),
        );
        ```
    </Tabs.Tab>
</Tabs>
